/*
 * This file and its contents are supplied under the terms of the
 * Common Development and Distribution License ("CDDL"), version 1.0.
 * You may only use this file in accordance with the terms of version
 * 1.0 of the CDDL.
 *
 * A full copy of the text of the CDDL should have accompanied this
 * source.  A copy of the CDDL is also available via the Internet at
 * http://www.illumos.org/license/CDDL.
 */

/*
 * Copyright (c) 2019, DilOS Team
 */

#include <sys/types.h>
#include <sys/wait.h>

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

#define	SYSLOG_NAMES	1
#include <syslog.h>

void
zsyslog(char **argv)
{
	const char	*login;
	char		*buf, *ptr, *env;
	int		i, len, priority = -1, facility = -1, retcode;
	size_t		mem, pos;
	pid_t		pid;

	if ((env = getenv("ZSYSLOG")) == NULL) {
		/* don't log anything */
		return;
	} else if ((pid = fork()) <= 0) {
		/*
		 * for child process or on error
		 * we just return to the main process
		 */
		return;
	} else if ((env = strdup(env)) != NULL) {
		char		*level;
		const CODE	*cptr;
		/* facility.priority */
		level = strchr(env, '.');
		if (level != NULL) {
			*level = '\0';
			level++;
		}
		for (cptr = facilitynames; cptr->c_name != NULL; cptr++)
			if (strcasecmp(env, cptr->c_name) == 0) {
				facility = cptr->c_val;
				break;
			}
		if ((level != NULL) && (*level != '\0')) {
			for (cptr = prioritynames; cptr->c_name != NULL; cptr++)
				if (strcasecmp(level, cptr->c_name) == 0) {
					priority = cptr->c_val;
					break;
				}
		}
		free(env);
	}

	for (buf = NULL, pos = mem = 0, i = 0; argv[i] != NULL; i++) {
		len = strlen(argv[i]) + 1;
		if (argv[i + 1] != NULL)
			len++;
		mem += len;
		ptr = realloc(buf, mem);
		if (ptr == NULL) {
			free(buf);
			return;
		}
		buf = ptr;
		ptr = buf + pos;
		if (argv[i + 1] != NULL)
			len = snprintf(ptr, mem - pos, "%s ", argv[i]);
		else
			len = snprintf(ptr, mem - pos, "%s", argv[i]);
		if (len <= 0) {
			free(buf);
			return;
		}
		pos += len;
	}

	login = getenv("LOGNAME");
	if (login == NULL) {
		login = getenv("USER");
		if (login == NULL)
			login = "*unknown*";
	}

	if (facility < 0)
		facility = LOG_LOCAL3;
	if (priority < 0)
		priority = LOG_DEBUG;

	i = retcode = 0;
	if (waitpid(pid, &i, 0) == pid) {
		/* get the return code */
		retcode = WEXITSTATUS(i);
	}

	openlog(argv[0], LOG_PID, facility);
	syslog(priority, "%s: %s; retcode = %d", login, buf, retcode);
	closelog();
	free(buf);

	/*
	 * we are the parent process, just exit here
	 * with the return code
	 */
	exit(retcode);
}
